package com.xnxkj.wx.micro.mch.utils;

import com.xnxkj.wx.micro.mch.bean.Certificate;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import javax.security.cert.X509Certificate;
import java.util.Base64;

/**
 * 加解密工具
 */
public class EncryptUtils {
    private static final String ALGORITHM = "AES/GCM/NoPadding";
    private static final int TAG_LENGTH_BIT = 128;
    private static final String CIPHER_PROVIDER = "SunJCE";
    private static final Charset CHAR_ENCODING = StandardCharsets.UTF_8;
    private static final String TRANSFORMATION_PKCS1Padding = "RSA/ECB/PKCS1Padding";

    /**
     * 解密平台证书
     * @param encryptCertificate 加密的证书内容
     * @param aes_key APIv3密钥
     */
    public static byte[] aesGcmDecrypt(Certificate.EncryptCertificate encryptCertificate, String aes_key) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        final Cipher cipher = Cipher.getInstance(ALGORITHM, CIPHER_PROVIDER);
        SecretKeySpec key = new SecretKeySpec(aes_key.getBytes(), "AES");
        GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, encryptCertificate.getNonce().getBytes());
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        cipher.updateAAD(encryptCertificate.getAssociatedData().getBytes());
        return cipher.doFinal(Base64.getDecoder().decode(encryptCertificate.getCipherText()));
    }

    /**
     * 对敏感信息加密
     * @param certificate 证书
     * @param content 加密内容
     */
    public static String rsaEncrypt(X509Certificate certificate, String content) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        PublicKey publicKey = certificate.getPublicKey();
        Cipher ci = Cipher.getInstance(TRANSFORMATION_PKCS1Padding, CIPHER_PROVIDER);
        ci.init(Cipher.ENCRYPT_MODE, publicKey);
        return Base64.getEncoder().encodeToString(ci.doFinal(content.getBytes(CHAR_ENCODING)));
    }
}
